Skip to content

Newsletter: flip the modernization filter default + retire legacy (PR 6 / #48530)#48613

Open
keoshi wants to merge 25 commits into
try/newsletter-modernization-wpds-cardsfrom
try/newsletter-modernization-flip-flag
Open

Newsletter: flip the modernization filter default + retire legacy (PR 6 / #48530)#48613
keoshi wants to merge 25 commits into
try/newsletter-modernization-wpds-cardsfrom
try/newsletter-modernization-flip-flag

Conversation

@keoshi
Copy link
Copy Markdown
Contributor

@keoshi keoshi commented May 7, 2026

Closes #48530 — final PR of the six-PR Newsletter modernization rollout. Stacked on #48608 (Settings on WPDS Card primitives). Once #48608 merges, GitHub auto-flips this PR's base to trunk.

Proposed changes

  • Flip the modernization filter default to true. Newsletter\Settings::is_modernized() now defaults the rsm_jetpack_ui_modernization_newsletter filter to true. Every Jetpack site lands on the unified Subscribers/Settings chassis without any opt-in. Hosts that need the legacy AdminPage surface back can add_filter( 'rsm_jetpack_ui_modernization_newsletter', '__return_false' );. The Subscribers REST gate (class-wpcom-rest-api-v2-endpoint-subscribers-list.php) flips its default the same way so the proxy registers without an explicit filter.
  • Retire the standalone Subscribers wp-admin menu and Calypso shortcut. modules/subscriptions.php drops the add_subscribers_menu method (the "Subscribers ↗" Calypso link on self-hosted) and the Subscribers_Dashboard::init() call (the wp-admin Subscribers page registration). jetpack-mu-wpcom's wpcom-admin-menu.php collapses the // Jetpack > Subscribers. if/else into a wpcom_hide_submenu_page call so nothing surfaces the Calypso link, and 'subscribers' drops out of the Jetpack submenu order list. Newsletter is the single Subscribers entry now.
  • Remove the subscribers-dashboard package. Delete projects/packages/subscribers-dashboard/ outright and pull automattic/jetpack-subscribers-dashboard from plugins/jetpack, packages/jetpack-mu-wpcom, and packages/masterbar. Refresh composer.lock (Jetpack plugin) and pnpm-lock.yaml so the autoload classmap and pnpm graph stop carrying the package.
  • Wire the jetpack_newsletter_tab_view Tracks event. Fire it from NewsletterPage's onTabChange with { site_type, tab } whenever the visitor flips to a different tab; same-tab clicks no-op. Analytics init was already lifted to the page Stage in PR 2, but PR 2's load_admin_scripts short-circuit was also skipping the jp-tracks enqueue, so events queued into _tkq forever and pixel.wp.com/t.gif never fired. Move the jp-tracks enqueue above the modernization short-circuit so the Tracks transport loads on both surfaces.

ARIA + RTL audited in the browser:

  • Tabs primitive ships role="tablist" + role="tab" + role="tabpanel" with the right aria-selected / aria-labelledby / tabindex plumbing out of the box (Base UI under the hood).
  • Setting dir="rtl" flips the page header (logo + "Newsletter" sit on the right, in the correct semantic order), the Subscribers/Settings tab nav, and the Newsletter card's two-link footer (Privacy / Manage subscribers bracket the row in flipped positions).

Related product discussion/links

Does this pull request change what data or activity we track or use?

  • REST surface. No new endpoints — the Subscribers proxy filter default flips along with the chassis filter, but the same routes register.
  • New Tracks event. jetpack_newsletter_tab_view fires with { site_type, tab } on tab change. No new identifiers or PII; matches the pattern other Jetpack page-tab events use.
  • No changes to privacy notices.
  • add_script_data payload. No new keys (the subscriberManagementEnabled key landed in PR 4).

Testing instructions

Pull this branch, run pnpm install, composer install inside projects/plugins/jetpack/, and pnpm jetpack build packages/newsletter --deps to refresh the Newsletter package and its dependencies.

Default-on (the new behaviour)

  • Make sure no add_filter( 'rsm_jetpack_ui_modernization_newsletter', ... ) lives in any mu-plugin / wp-config.php / theme / Code Snippet.
  • Visit wp-admin/admin.php?page=jetpack-newsletter. The unified chassis renders straight away — page header with the Jetpack mark + "Newsletter", Subscribers/Settings tabs, the WPDS Card layout in Settings, the Subscribers DataViews list under the Subscribers tab.
  • The Jetpack sidebar no longer shows "Subscribers ↗" (or a wp-admin "Subscribers" page on hosts that previously had jetpack_wp_admin_subscriber_management_enabled on).
  • Confirm pixel.wp.com/t.gif?...&_en=jetpack_newsletter_tab_view&tab=... requests fire when switching tabs (DevTools → Network, filter pixel.wp.com).

Opt-out path

  • Add add_filter( 'rsm_jetpack_ui_modernization_newsletter', '__return_false' ); to a mu-plugin or Code Snippet.
  • Hard-refresh — the legacy Newsletter Settings page returns (Jetpack-styled AdminPage chrome with the green logo header). The settings still save, the cards still render with WPDS primitives (PR 5 already updated the shared body).

RTL smoke check

  • Switch to an RTL admin language (e.g., Hebrew) or set dir="rtl" on <html>/<body> in DevTools.
  • The page header (logo + Newsletter), tab nav, save buttons, and the Newsletter card's two-link footer all flip to the opposite side; nothing collides with the wp-admin sidebar.

Keyboard / ARIA smoke check

  • Tab into the tab nav, arrow keys cycle Subscribers ↔ Settings, Enter / Space activates. Screen reader announces "Subscribers, tab, 1 of 2, selected" / "Settings, tab, 2 of 2".

Screenshots

To be added once the PR review begins (the visual surface is the same as #48608 with the modernization filter implicitly on).

keoshi added 15 commits May 7, 2026 09:53
Surface the value of `jetpack_wp_admin_subscriber_management_enabled` as
`subscriberManagementEnabled` in the Newsletter script data so the
modernized dashboard can hide the Subscribers tab on hosts that defer
subscriber management to Calypso, instead of inferring intent from the
URL we ship under `subscriberManagementUrl`.

Pure metadata — the filter remains the source of truth and the existing
URL shape is unchanged.
Introduce `NewsletterPage` as the shared shell for the modernized
dashboard: a single `Page` from `@wordpress/admin-ui` wraps a persistent
`Tabs.Root` from `@wordpress/ui` driven by a `?tab=` URL param so the
animated active-tab indicator slides between Subscribers and Settings
instead of remounting on each route hop. Switching tabs also strips the
subscriber-detail params (`subscriber`, `u`) so the inspector doesn't
hitchhike across to Settings.

The chrome polishes the page surface to match Forms: an off-white
background so cards stand out, a sticky page header without a bottom
rule, a sticky tab row pinned by a ResizeObserver-tracked CSS variable,
and a flex chain that lets DataViews fill the viewport on Subscribers
while letting Settings keep its content-tall scrolling model.

Hides the Subscribers tab when
`jetpack_wp_admin_subscriber_management_enabled` is filtered to false,
so hosts that defer subscriber management to Calypso land on a
Settings-only page.
Move the 9 settings sections, their state hooks, and the save handlers
into a new `NewsletterSettingsBody` component under
`src/settings/newsletter-settings.tsx`. The legacy
`NewsletterSettingsApp` becomes a thin chrome wrapper that mounts the
body inside `AdminPage` / `Container` / `Col` and runs the WP.com
connection check before passing `hasConnectedOwner` and `connectUrl`
in as props. The 9 sections themselves are unchanged.

The split lets the modernized dashboard mount the body inside its
`Tabs.Panel` without dragging `@automattic/jetpack-components` and
`@automattic/jetpack-connection` (and their SCSS chains) through the
wp-build pipeline. Snackbars dispatch straight to `@wordpress/notices`'s
`noticesStore` — the legacy chrome keeps its `<GlobalNotices />` for
surfacing, the wp-build polyfills' `SnackbarNotices` already covers the
modernized side.

Also switch `newsletter-section.tsx` to import `getRedirectUrl` via
the package's `./tools/jp-redirect` subpath, so dropping a section
into the wp-build bundle doesn't drag the rest of the components
package in with it.
Add a `./components/wpcom-support-link` export so consumers that only
need the support-link helper can import it without dragging the rest of
the components barrel — and crucially the SCSS-laden `Nudge` — through
their bundler. The Newsletter modernized dashboard switches its
categories section to the new subpath so the wp-build pipeline can
resolve the section without pulling in upgrade-nudge.
… its panel

Replace the inline `Page` chrome with `NewsletterPage` and feed both
tabs from the same `Tabs.Root`. `?tab=settings` flips to the Settings
panel, where `NewsletterSettingsBody` renders the existing 9-section
form unchanged on its legacy primitives — PR 5 will move those onto
WPDS `Card`. Subscribers stays the default and inherits the row-action
and header-action behaviour shipped in PR 3.

The route module gains `@automattic/jetpack-api`,
`@automattic/jetpack-shared-extension-utils`, and `@wordpress/url` so
the settings body and its sections — which import from those packages —
resolve once they're mounted inside the wp-build bundle. The inactive
panel renders `null` so we don't pay for the other view's data
fetching until a visitor opens it.
`route.inspector` decides visibility from search params alone, so a
deep-link like `?tab=settings&subscriber=123` would otherwise pop the
detail panel open on top of the Settings page. Bail out early when the
active tab is Settings; `NewsletterPage` already strips `subscriber`
and `u` on tab change, but this guard covers manual URL edits too.
…ssis

`@wordpress/route`'s `navigate` doesn't accept a search-updater
function, so passing `search: ( prev ) => ( ... )` no-ops the search
state — the new `?tab=` param never made it into the router and tabs
never switched. Pass an object literal instead, then read the active tab
from `search.tab` as before.

When `jetpack_wp_admin_subscriber_management_enabled` is filtered to
false the page is Settings-only, but the stage was still rendering two
`Tabs.Panel`s under a chrome that no longer wrapped them in a
`Tabs.Root`. That tripped the Base UI invariants
(`TabsRootContext is missing`, then `Tab/Panel count mismatch` once we
trimmed one Panel). Pin `activeTab` to `settings` when subscribers
are hidden and render `<NewsletterSettingsBody />` directly, with no
`Tabs.Panel` wrapper, so the Settings-only path never crosses the Tabs
primitive at all.
…e stage

`@wordpress/admin-ui`'s `Page` puts `overflow: auto` on the body
wrapper itself, so the body wrapper — not the outer stage — is the
scroll container. The page header is a sibling of the body wrapper,
not a parent. That meant the previous `top: var(--header-height)` on
`.jetpack-newsletter-page__tabs-row` was sticking the row 92px below
the body-wrapper top, leaving an empty band where the dataviews chrome
showed through. Switch the sticky offset to `top: 0` (the body
wrapper already starts directly under the page header) and drop the
`ResizeObserver` that fed `--jetpack-newsletter-header-height` —
nothing reads it anymore.

Admin-ui also sets `flex: 1 1 auto` on every direct child of the body
wrapper, which was outweighing the tabs-row's `flex-shrink: 0` and
collapsing it to ~24px so the 48px tab buttons clipped out of view.
Bump the tabs-row selector to mirror admin-ui's
`> :not(.admin-ui-page__header):not(.jetpack-footer) > *` path so
`flex: 0 0 auto` actually wins, and the bar grows to its natural
height with the active-tab indicator visible.
Subscribers ships header actions ("Add subscribers" + the More menu)
that pulled the header's title row to 36px, while Settings shipped no
actions and let the row collapse to its 28px text height — so swapping
tabs nudged the whole sticky row plus everything underneath by 8px.

Pin `.admin-ui-page__header > *:first-child` to a 36px min-height so
the title row matches the action-button height regardless of whether
actions are present. The 8px jump is gone, the tab bar no longer
re-positions on tab change.
Render `JetpackLogo` (mark only, no text) inline with "Newsletter"
in the page-header title slot, matching the wp-build chassis convention
that Forms, Backup, and VideoPress already use. The mark sits inside a
`Stack` with an 8px gap so the brand and the product name read as one
title unit, and the `ariaLabel` keeps the screen-reader name as plain
"Newsletter".

The logo arrives via the package's `./jetpack-logo` subpath so we
don't drag the rest of `@automattic/jetpack-components` (and its
SCSS chain) into the wp-build bundle.
The default header was leaving roughly 16px of slack between the
subtitle and the tab nav directly underneath, which read as a stray
band of empty page surface once the tab row was anchored to the body
wrapper. Pin `padding-block-end` on `.admin-ui-page__header` to
`--wpds-dimension-padding-xs` (4px) so the tab nav docks straight up
against the subtitle.
Move all 9 settings sections from `@wordpress/components`'s
`Card` / `CardHeader` / `CardBody` / `CardFooter` over to
`Card.Root` / `Card.Header` / `Card.Title` / `Card.Content` from
`@wordpress/ui`. `__experimentalHeading` (legacy heading inside the
header) becomes `Card.Title`; `__experimentalText` becomes WPDS
`Text`. Section internals — DataForm fields, save handlers, change
tracking — stay byte-for-byte identical.

WPDS `Card` doesn't ship a `Footer` slot, so the row that used to
live inside `<CardFooter>` becomes a `<div className="newsletter-card-footer">`
at the bottom of `<Card.Content>`. The shared style:
* save-button rows (Subscriptions, Newsletter categories, Sender
  settings, Welcome email) right-align via `justify-content: flex-end`,
* the Newsletter section's two-link row (Privacy + Manage subscribers)
  brackets via a `:has(> :nth-child(2))` rule that switches to
  `space-between` only when there's more than one child.

Save and action buttons (`Save`, `Add plans` / `Manage plans`) opt
into `__next40pxDefaultSize` so they ship the WordPress 7 default
height ahead of the upgrade. Pure refactor — no behaviour changes.
…elow

The settings body stacked its cards with `gap="md"` (12px), which
left them sitting too close together on the modernized chassis once
they got the new WPDS Card chrome. Switch the inner and outer
`Stack`s to `gap="xl"` so each card pair sits exactly 24px apart
via `--wpds-dimension-gap-xl` — same rhythm as the page-header
padding inset, no magic numbers.

Add a `padding-block-end` of `--wpds-dimension-padding-3xl` (32px)
to `.newsletter-settings` so the last card has room before the
page bottom on overflow scroll.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the try/newsletter-modernization-flip-flag branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack try/newsletter-modernization-flip-flag
bin/jetpack-downloader test jetpack-mu-wpcom-plugin try/newsletter-modernization-flip-flag

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions Bot added [Feature] Masterbar WordPress.com Toolbar and Dashboard customizations [mu wpcom Feature] Wpcom Admin Menu [Package] Jetpack mu wpcom WordPress.com Features [Package] Masterbar [Package] Newsletter [Package] Subscribers Dashboard [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Tests] Includes Tests labels May 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: June 2, 2026
    • Code freeze: June 1, 2026

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@github-actions github-actions Bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label May 7, 2026
@keoshi keoshi self-assigned this May 7, 2026
@keoshi keoshi added [Status] Needs Review This PR is ready for review. and removed [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. labels May 7, 2026
@keoshi keoshi requested review from CGastrell, dhasilva and ilonagl May 7, 2026 16:27
keoshi added 10 commits May 7, 2026 12:52
Bring the prototype's placement-card surface back: a selectable card
composed from `<label htmlFor>` + `CheckboxControl`, a 16:9-ish SVG
wireframe slot, a caption with an optional "Preview and edit" link,
and a brand-toned active-stroke driven by `data-checked="true"`.
Ported verbatim — same component API the prototype settled on so the
SubscriptionsSection can swap its flat `ToggleWithEditorLink` rows for
a 2×2 grid of cards in the next commit.

The four illustration components (`OverlayIllustration`,
`PopupIllustration`, `EndOfPostIllustration`, `FloatingIllustration`)
ship as inline 294×192 SVG wireframes — pure vector, no external
assets. Subgroup heading and `<fieldset>` reset styles join the
package stylesheet alongside the placement-card scss for the
neighbouring Navigation / Comments groups.
Replace the flat `ToggleWithEditorLink` rows in the Subscriptions card
with a 2×2 grid of `PlacementCard`s — overlay, modal, end-of-post,
floating button — each backed by its own SVG wireframe and an optional
"Preview and edit" link to the matching site-editor template part.
Navigation and Comments stay as inline `ToggleControl` subgroups
inside the same card so the whole subscription configuration reads
without scrolling between cards.

Telemetry catches up with the prototype:

* `jetpack_newsletter_placement_toggle` fires on every placement
  card flip, tagged with the placement slug + new value.
* `jetpack_newsletter_placement_preview_click` fires when the user
  clicks a card's preview link.
* `jetpack_newsletter_section_save` payload gains
  `changed_keys` / `change_count` so we can see what's actually in
  each user's batch instead of just the section name. The orchestrator
  will start passing the staged keys in the next commit.

The section accepts an optional `changedKeys` prop (still optional
for now so the orchestrator wiring lands separately without breaking
the build) and falls back to an empty array if the parent doesn't
supply it.
The legacy `NewsletterSection` doubled as a master `subscriptions`
toggle and a "send new posts as newsletters by default" toggle.
Now that the master toggle moves to the global Newsletter module
activation control, drop it from this UI and reshape the surviving
`wpcom_newsletter_send_default` field into a focused, email-themed
card called **Email defaults**.

While the section was being reshaped:

* Drop the "Privacy information" + "Manage all subscribers" footer
  links — they don't fit the email-defaults framing, and the latter is
  redundant with the Subscribers tab now living one click away.
* Rename the file to `sections/email-defaults-section.tsx` and the
  exported component to `EmailDefaultsSection`. Update
  `sections/index.ts` accordingly.

Reshuffle the IA in `newsletter-settings.tsx` to walk users from
activation flavour → distribution → email behaviour → categorisation:

  Paid → Subscriptions → Email defaults → Email content → Email byline
  → Email sender settings → Email reply-to settings → Welcome email →
  Newsletter categories.

Drop the always-editable wrapper around the deleted
`NewsletterSection`; everything now sits inside the same
`<Disabled isDisabled={ ! data.subscriptions }>` boundary that gates
the rest of the page on module status.
Subscriptions, Sender, Categories, and Welcome each fire a
`jetpack_newsletter_section_save` Tracks event when the user clicks
their Save button. Until now those events only carried the section
name — useful for counts but not for understanding which fields users
actually flip together inside a single batch.

Each section now accepts an optional `changedKeys: string[]` prop and
forwards it as `changed_keys` (comma-joined) + `change_count` on the
save event. The orchestrator wires it from the changeset state it
already maintains for each section's manual save (`subscriptionChanges`,
`senderNameChanges`, `newsletterCategoriesChanges`,
`welcomeEmailChanges` → `Object.keys()`).
Every Jetpack site now lands on the unified Subscribers/Settings
chassis we've been building since PR 1. The legacy `AdminPage`
chrome stays in the bundle behind the same filter, so hosts that
need the old surface back can opt out with
`add_filter( 'rsm_jetpack_ui_modernization_newsletter', '__return_false' );`
until the legacy code paths are removed in a follow-up.
The unified Newsletter page now owns the Subscribers tab, so neither
the wp-admin Subscribers submenu nor the "Subscribers ↗" Calypso
link belongs in the sidebar anymore.

* `modules/subscriptions.php`: drop the `add_subscribers_menu`
  method (and its `jetpack_admin_menu` hook) that registered the
  Calypso shortcut on self-hosted, plus the `Subscribers_Dashboard`
  init that registered the standalone wp-admin Subscribers page on
  hosts with `jetpack_wp_admin_subscriber_management_enabled` on.
  Drop the now-unused `Admin_Menu` and `Redirect` imports.
* `jetpack-mu-wpcom/wpcom-admin-menu.php`: collapse the
  `// Jetpack > Subscribers.` if/else into a single
  `wpcom_hide_submenu_page` call — the Calypso link no longer surfaces
  here either way, but we keep the hide so anything else that adds it
  back stays out of the sidebar. Drop `Subscribers_Dashboard` import
  and remove `'subscribers'` from the Jetpack submenu order list.

Newsletter is now the single Subscribers entry point. The
`subscribers-dashboard` package will be deleted in the next commit.
Now that no plugin instantiates `Subscribers_Dashboard` (the previous
commit retired both call sites), the package has no consumers and can
go. Delete `projects/packages/subscribers-dashboard/` outright.

Pull the `automattic/jetpack-subscribers-dashboard` dep out of
`plugins/jetpack/composer.json`, `packages/jetpack-mu-wpcom/composer.json`,
and `packages/masterbar/composer.json` (none of those packages were
using it directly), refresh the Jetpack plugin's `composer.lock` and
the workspace `pnpm-lock.yaml` so the autoload classmap and pnpm
graph stop carrying the package. Standalone `Subscribers` page is
fully retired — Newsletter is the single Subscribers entry now.
Record a tracks event whenever the visitor flips to a different tab —
`{ site_type, tab }`. The guard skips the no-op case where
`next === activeTab`, so refreshes and same-tab nav don't pollute the
counts. Analytics is already initialized at the page Stage (PR 2), so
the event reaches Tracks immediately on first interaction.
PR 2 lifted analytics initialization to the page Stage but
`load_admin_scripts` was still short-circuiting before any script
enqueue ran when modernization was on. `analytics.initialize` queues
events into `window._tkq`, but without the Tracks transport
(`stats.wp.com/w.js`) loaded, the queue grows forever and no
`pixel.wp.com/t.gif` requests fire — telemetry from PR 6's new
`jetpack_newsletter_tab_view` event went nowhere.

Move the `jp-tracks` enqueue above the modernized short-circuit so
it runs on both surfaces; everything else (the legacy
`jetpack-newsletter` bundle, JetpackScriptData, etc.) stays gated to
the legacy path.
@keoshi keoshi force-pushed the try/newsletter-modernization-flip-flag branch from 7f749e1 to cc6bb99 Compare May 7, 2026 18:43
@dhasilva dhasilva force-pushed the try/newsletter-modernization-wpds-cards branch from 77b3ffe to 4e9e166 Compare May 12, 2026 01:15
dhasilva added a commit that referenced this pull request May 12, 2026
The Card-primitives migration shared `NewsletterSettingsBody` between
the legacy `wp-admin/admin.php?page=jetpack-newsletter` route and the
modernized chassis, but the IA reshape (master toggle removed,
`EmailDefaultsSection` split out, placement-card grid, dropped
privacy/manage links) had no flag wrapping it — so the legacy surface
silently picked up every modernized behaviour even with
`rsm_jetpack_ui_modernization_newsletter` off. That made the
changelog claim "no user-visible change unless the flag is enabled"
wrong on the legacy page.

Add a defaulted-false `isModernized` prop to `NewsletterSettingsBody`
and branch only the section composition on it. The shared state —
API fetch, optimistic update, change tracking, snackbar dispatch —
stays single-source. The chassis passes `isModernized` from
`routes/dashboard/stage.tsx`; the legacy mount in
`src/settings/index.tsx` doesn't change at all (default suffices).

Legacy branch keeps trunk's exact composition: `NewsletterSection`
(master `subscriptions` toggle + Privacy / Manage subscribers footer
links) outside the disabled-by-subscriptions wrapper, then
`LegacySubscriptionsSection` (flat `ToggleWithEditorLink` list
grouped into Homepage / Navigation / Comments subgroups) inside it,
followed by the trunk section order. Both legacy files retire
together with the legacy chrome in #48613.

Also fix `tests/settings.test.jsx`: the jest mock for
`../src/settings/sections` lagged the renames in commit 6 (no
`EmailDefaultsSection`), so the consumer rendered `undefined` and
the test suite dropped from 8/8 to 4/8. The mock now matches the
real exports, including `LegacySubscriptionsSection` and
`NewsletterSection`. Suite is 8/8 again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Masterbar WordPress.com Toolbar and Dashboard customizations [mu wpcom Feature] Wpcom Admin Menu [Package] Jetpack mu wpcom WordPress.com Features [Package] Masterbar [Package] Newsletter [Package] Subscribers Dashboard [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Status] Needs Review This PR is ready for review. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant